package com.penngo.gui.dfdiff.view;


import com.penngo.gui.dfdiff.utils.Adler32Utils;
import com.penngo.gui.dfdiff.utils.DateUtil;
import com.penngo.gui.dfdiff.utils.LogUtils;
import org.jdesktop.swingx.treetable.AbstractTreeTableModel;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.logging.Logger;

public class FolderModel extends AbstractTreeTableModel {
    private Logger log = LogUtils.getLogger(FolderModel.class);
    private FolderNode root;
    //private JXTreeTable treeTable;
    private FolderTable.Type type;
    private File rootFile;
    public FolderModel(FolderNode root, FolderTable.Type type){
        this.root = root;
        this.root.setDirectory(true);
        this.type = type;
    }

    public void setFile(File rootFile, FolderTable.FinishListener listener){
        this.rootFile = rootFile;
        log.info("====================开始====================");
        if(type == FolderTable.Type.LEFT){
            root.setLeft(FolderNode.CheckType.YES);

        }
        else if(type == FolderTable.Type.RIGHT){
            root.setRight(FolderNode.CheckType.YES);
        }

        new Thread(()->{
            clearPath(root);
            if(rootFile.isDirectory()){
                loopPath(root, rootFile);
                log.info("====================完成====================");
                listener.action();
            }
            else{
                log.info("error====================" + rootFile.getAbsolutePath());
//                root.setDirectory(false);
            }
        }).start();
    }
    private void clearPath(FolderNode root){
        List<FolderNode> children = root.getChildren();
        if(children.size() > 0){
            List<FolderNode> removeList = new ArrayList<>();
            for(FolderNode node:children){
                if(type == FolderTable.Type.LEFT && node.getLeftExist() == FolderNode.ExistType.YES){
                    node.setLeftExist(FolderNode.ExistType.NOT);
                }
                else if(type == FolderTable.Type.RIGHT && node.getRightExist() == FolderNode.ExistType.YES){
                    node.setRightExist(FolderNode.ExistType.NOT);
                }
                if(node.getLeftExist() != FolderNode.ExistType.YES && node.getRightExist() != FolderNode.ExistType.YES){
                    removeList.add(node);
                }
            }
            children.removeAll(removeList);

        }
        if(children.size() > 0){
            for(FolderNode node:children){
                clearPath(node);
            }
        }
    }


    private void loopPath(FolderNode parentNode, File parentFile){
        File[] files = parentFile.listFiles();
        List<Object[]> dirList = new ArrayList<>();
        boolean isDirSave = true;//目录下所有文件相同，目录才相同
        for(File file:files){
            // 过滤隐藏文件
            if(file.isHidden() == true){
                continue;
            }
            FolderNode node = getChildNode(parentNode, file);
//            log.info("loopPath====" + file.getAbsolutePath());
            // 设置是否已遍历、是否存在、文件摘要
            if(type == FolderTable.Type.LEFT){
                node.setLeftExist(FolderNode.ExistType.YES);
                if(node.isDirectory() == false){
                    node.setLeftCode(Adler32Utils.getAdler32(file));
                }

            }
            else if(type == FolderTable.Type.RIGHT){
                node.setRightExist(FolderNode.ExistType.YES);
                if(node.isDirectory() == false){
                    node.setRightCode(Adler32Utils.getAdler32(file));
                }
            }
            // 如果为目录，继续循环遍历
            if(node.isDirectory()){
                dirList.add(new Object[]{node, file});
                if(node.getLeftExist() == FolderNode.ExistType.YES && node.getRightExist() == FolderNode.ExistType.YES){
                    node.setSame(true);
                }
            }
            // 如果为文件
            else{
                if(node.getLeftExist() == FolderNode.ExistType.YES && node.getRightExist() == FolderNode.ExistType.YES){
                    node.setSame(node.getLeftCode().equals(node.getRightCode()));
                }
            }
            if(node.isSame() == false && isDirSave == true){
                isDirSave = false;
            }
        }
        for(Object[] objs:dirList){
            FolderNode node = (FolderNode)objs[0];
            File file = (File)objs[1];
            loopPath(node, file);
            if(node.isSame() == false && isDirSave == true){
                isDirSave = false;
            }
        }
        if(isDirSave == false){
            parentNode.setSame(false);
        }
    }

    /**
     * 检查当前文件是否已在树中
     * @param parentNode
     * @param file
     */
    private FolderNode getChildNode(FolderNode parentNode, File file){
        List<FolderNode> nodes = parentNode.getChildren();
        String path = file.getAbsolutePath().replace(rootFile.getAbsolutePath(), "");

        FolderNode node = null;
        if(nodes != null){
            for(FolderNode nodeTemp:nodes){
                nodeTemp.setLeft(root.getLeft());
                nodeTemp.setRight(root.getRight());
                if(nodeTemp.getPath().equals(path)){
                    node = nodeTemp;
                    break;
                }
            }
        }

        if(node == null){
            node = new FolderNode(file.getName(), file.length(), file.lastModified());
            node.setPath(file.getAbsolutePath().replace(rootFile.getAbsolutePath(), ""));
            node.setDirectory(file.isDirectory());
            nodes.add(node);
            Collections.sort(nodes, Comparator.comparing(FolderNode::getName));
        }
        node.setLeft(root.getLeft());
        node.setRight(root.getRight());
        return node;
    }

    @Override
    public int getColumnCount() {
        return 3;
    }

    @Override
    public Object getValueAt(Object node, int column) {
//        log.info("getValueAt: " + node + ", " + column);
        FolderNode treenode = (FolderNode) node;
        switch (column) {
            case 0:
                if(type == FolderTable.Type.LEFT && treenode.getLeftExist() == FolderNode.ExistType.YES ||
                    type == FolderTable.Type.RIGHT && treenode.getRightExist() == FolderNode.ExistType.YES){
                    return treenode;
                }
                else{
                    FolderNode treenode2 = treenode.clone();
                    treenode2.setName("");
                    return treenode2;
                }
//                return treenode;
            case 1:
                long size = treenode.getSize();
                String value = size + " B";
                if(size > 1024){
                    size = size / 1024;
                    value = size + " KB";
                }
                if(size > 1024){
                    size = size / 1024;
                    value = size + " MB";
                }
                if(size > 1024){
                    size = size / 1024;
                    value = size + " GB";
                }
                if(treenode.isDirectory() == true){
                    return "";
                }
                else if(type == FolderTable.Type.LEFT && treenode.getLeft() == FolderNode.CheckType.YES
                        && treenode.getLeftExist() == FolderNode.ExistType.YES ||
                        type == FolderTable.Type.RIGHT && treenode.getRight() == FolderNode.CheckType.YES
                        && treenode.getRightExist() == FolderNode.ExistType.YES){
                    return value;
                }
            case 2:
                if(type == FolderTable.Type.LEFT && treenode.getLeft() == FolderNode.CheckType.YES
                            && treenode.getLeftExist() == FolderNode.ExistType.YES ||
                        type == FolderTable.Type.RIGHT && treenode.getRight() == FolderNode.CheckType.YES
                            && treenode.getRightExist() == FolderNode.ExistType.YES){
                    return DateUtil.secondToDateStr(treenode.getUpdateTime());
                }
                else{
                    return "";
                }

            default:
                return "Unknown";
        }
    }

    @Override
    public Object getChild(Object node, int index) {
        FolderNode treenode = (FolderNode) node;
        return treenode.getChildren().get(index);
    }

    @Override
    public int getChildCount(Object parent) {
        //log.info("getChildCount======" );
        FolderNode treenode = (FolderNode) parent;

        if(type == FolderTable.Type.LEFT && treenode.getLeft() == FolderNode.CheckType.YES ||
                type == FolderTable.Type.RIGHT && treenode.getRight() == FolderNode.CheckType.YES){
            return treenode.getChildren().size();
        }
        else{
            return 0;
        }
    }

    @Override
    public int getIndexOfChild(Object parent, Object child) {
        FolderNode treenode = (FolderNode) parent;
        for (int i = 0; i < treenode.getChildren().size(); i++) {
            if (treenode.getChildren().get(i) == child) {
                return i;
            }
        }
        return 0;
    }
    public boolean isLeaf(Object node) {
        FolderNode treenode = (FolderNode) node;
//        log.info("isLeaf======" + treenode.getName() + "," + !treenode.isDirectory());
        return !treenode.isDirectory();
//        if (treenode.getChildren().size() > 0) {
//            return false;
//        }
//        return true;
    }
    @Override
    public Object getRoot() {
        return root;
    }

    public File getRootFile() {
        return rootFile;
    }

//    public void setTreeTable(JXTreeTable treeTable) {
//        this.treeTable = treeTable;
//    }

}
